using Autofac;
using Autofac.Core;
using Autofac.Extensions.DependencyInjection;
using DogAPI.Filter;
using HelperCommon.AOP.MemoryCache;
using HelperCommon.AOP.RedisCache;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using NLog;
using NLog.Extensions.Logging;
using SqlSugar;
using SqlSugar.Extensions;
using StackExchange.Redis;
using Swashbuckle.AspNetCore.Filters;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(a =>
{
    // 开启加权小锁(暂时不知道什么意思)
    a.OperationFilter<AddResponseHeadersFilter>();
    //（接口显示认证角色信息）
    a.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
    // 在header中添加token，传递到后台（添加小锁）
    a.OperationFilter<SecurityRequirementsOperationFilter>();

    a.AddSecurityDefinition("oauth2", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
        Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}（注意两者之间是一个空格）\"",
        Name = "Authorization",        //jwt默认的参数名称
        In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中)
        Type = SecuritySchemeType.ApiKey//安全方案/类型(模式)APIkey
    });
});

builder.Services.AddMemoryCache();
builder.Services.AddSingleton<IMemoryCaching, MemoryCaching>();
builder.Services.AddSingleton<IRedisCaching,RedisCaching>();

builder.Services.AddSingleton<ConnectionMultiplexer>(sp =>
{
    //获取连接字符串
    string redisConfiguration = "127.0.0.1:6379,password=123456";

    var configuration = ConfigurationOptions.Parse(redisConfiguration, true);

    configuration.ResolveDns = true;

    return ConnectionMultiplexer.Connect(configuration);
});


//使用autofac工厂接替微软的
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
    builder.RegisterModule(new AutoFacMoudleReg());//添加注册规则模块儿
});

//注入Nlog
builder.Services.AddLogging(logging =>
{
    logging.AddNLog();
});

Logger logger = LogManager.GetCurrentClassLogger();

//注入SqlSugar
//注册上下文：AOP里面可以获取IOC对象
builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<ISqlSugarClient>(s =>
{
    SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
    {
        LanguageType = LanguageType.Chinese,
        DbType = DbType.SqlServer,//数据库类型
        IsAutoCloseConnection = true,//自动释放数据库连接
        ConnectionString = ""//连接字符串
    }, db =>
    {
        //sql执行前事件
        db.Aop.OnLogExecuting = (sql, pars) =>
        {
            logger.Debug(UtilMethods.GetNativeSql(sql, pars));
        };
        //sql执行完成事件
        db.Aop.OnLogExecuted = (sql, pars) =>
        {
            logger.Debug(UtilMethods.GetNativeSql(sql, pars));
        };
        //sql报错事件
        db.Aop.OnError = (exp) =>
        {
            logger.Debug(UtilMethods.GetNativeSql(exp.Sql, (SugarParameter[])exp.Parametres));
        };
        //修改SQL和参数的值
        db.Aop.OnExecutingChangeSql = (sql, pars) =>
        {
            //sql = "";
            return new KeyValuePair<string, SugarParameter[]>(sql, pars);
        };
    });
    return sqlSugar;
});

//注册bearer认证
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    var SigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("12345678912345671234567891234567"));
    //验证的参数
    o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {
        //验证密钥
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = SigningKey,
        //验证发行者
        ValidateIssuer = true,
        ValidIssuer = "发行人",
        //验证受众
        ValidateAudience = true,
        ValidAudience = "受众人",
        //验证有效期
        ValidateLifetime = true,
        ClockSkew = TimeSpan.FromSeconds(30),
        //必须有过期值/时间
        RequireExpirationTime = true
    };
    o.Events = new JwtBearerEvents()
    {
        //当JWT Bearer认证失败时，即请求未包含有效的JWT令牌或令牌验证失败，该事件会被触发
        OnChallenge = context =>
        {
            context.Response.Headers.Add("Token-Error", context.ErrorDescription);
            return Task.CompletedTask;
        },
        //当JWT Bearer认证过程中出现异常时，例如令牌过期、签名验证失败等情况，该事件会被触发
        OnAuthenticationFailed = context =>
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            var token = context.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", string.Empty).Replace("bearer", string.Empty).Trim();

            var jwtToken = jwtHandler.ReadJwtToken(token);

            if (jwtToken.Issuer != "发行人")
            {
                context.Response.Headers.Add("Token-Error-Iss", "issuer is wrong!");
            }

            if (jwtToken.Audiences.FirstOrDefault() != "受众人")
            {
                context.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!");
            }
            // 如果过期，则把<是否过期>添加到，返回头信息中
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return Task.CompletedTask;
        }
    };
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();